﻿using AGooday.AgChat.Api.Data;
using AGooday.AgChat.Api.Models;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;

namespace AGooday.AgChat.Api.Hubs
{
    public class ChatHub : Hub
    {
        private readonly ApplicationDbContext _context;
        private static readonly Dictionary<int, string> _userConnections = new Dictionary<int, string>();

        public ChatHub(ApplicationDbContext context)
        {
            _context = context;
        }

        public override async Task OnConnectedAsync()
        {
            var userId = int.Parse(Context.UserIdentifier);
            _userConnections[userId] = Context.ConnectionId;

            // Update user status to online
            var user = await _context.Users.FindAsync(userId);
            if (user != null)
            {
                user.Status = "online";
                await _context.SaveChangesAsync();

                // Notify friends about online status
                await NotifyFriendsStatusChange(userId, "online");

                // 通知用户有关好友申请的状态更新
                // 这里可以发送未处理的好友申请数量等信息
            }

            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {
            var userId = int.Parse(Context.UserIdentifier);
            _userConnections.Remove(userId);

            // Update user status to offline
            var user = await _context.Users.FindAsync(userId);
            if (user != null)
            {
                user.Status = "offline";
                user.LastSeen = DateTime.UtcNow;
                await _context.SaveChangesAsync();

                // Notify friends about offline status
                await NotifyFriendsStatusChange(userId, "offline");
            }

            await base.OnDisconnectedAsync(exception);
        }

        private async Task NotifyFriendsStatusChange(int userId, string status)
        {
            var friendIds = await _context.Friendships
                .Where(f => f.UserId == userId && f.Status == "accepted")
                .Select(f => f.FriendId)
                .ToListAsync();

            foreach (var friendId in friendIds)
            {
                if (_userConnections.TryGetValue(friendId, out var connectionId))
                {
                    await Clients.Client(connectionId).SendAsync("FriendStatusChanged", userId, status);
                }
            }
        }

        public async Task SendPrivateMessage(int receiverId, string content, string messageType = "text")
        {
            var senderId = int.Parse(Context.UserIdentifier);

            var message = new Message
            {
                SenderId = senderId,
                ReceiverId = receiverId,
                Content = content,
                MessageType = messageType,
                SentAt = DateTime.UtcNow
            };

            _context.Messages.Add(message);
            await _context.SaveChangesAsync();

            var sender = await _context.Users.FindAsync(message.SenderId);
            message.Sender = new User
            {
                Id = sender.Id,
                Username = sender.Username,
                Avatar = sender.Avatar
            };

            // Send to receiver if online
            if (_userConnections.TryGetValue(receiverId, out var connectionId))
            {
                await Clients.Client(connectionId).SendAsync("ReceivePrivateMessage", message);
            }

            // Send back to sender for confirmation
            await Clients.Caller.SendAsync("ReceivePrivateMessage", message);
        }

        public async Task SendGroupMessage(int groupId, string content, string messageType = "text")
        {
            var senderId = int.Parse(Context.UserIdentifier);

            // Check if user is member of the group
            var isMember = await _context.GroupMembers
                .AnyAsync(gm => gm.GroupId == groupId && gm.UserId == senderId);

            if (!isMember)
            {
                throw new HubException("You are not a member of this group");
            }

            var message = new Message
            {
                SenderId = senderId,
                GroupId = groupId,
                Content = content,
                MessageType = messageType,
                SentAt = DateTime.UtcNow
            };

            _context.Messages.Add(message);
            await _context.SaveChangesAsync();

            // Get all group members
            var memberIds = await _context.GroupMembers
                .Where(gm => gm.GroupId == groupId)
                .Select(gm => gm.UserId)
                .ToListAsync();

            // Send to all online group members
            foreach (var memberId in memberIds)
            {
                if (_userConnections.TryGetValue(memberId, out var connectionId) && memberId != senderId)
                {
                    await Clients.Client(connectionId).SendAsync("ReceiveGroupMessage", message);
                }
            }

            // Send back to sender for confirmation
            await Clients.Caller.SendAsync("ReceiveGroupMessage", message);
        }

        public async Task MarkMessageAsRead(int messageId)
        {
            var userId = int.Parse(Context.UserIdentifier);
            var message = await _context.Messages.FindAsync(messageId);

            if (message != null && (message.ReceiverId == userId || message.GroupId.HasValue))
            {
                message.IsRead = true;
                await _context.SaveChangesAsync();

                // Notify sender that message was read
                if (_userConnections.TryGetValue(message.SenderId, out var connectionId))
                {
                    await Clients.Client(connectionId).SendAsync("MessageRead", messageId);
                }
            }
        }

        public async Task Typing(int receiverId, bool isTyping)
        {
            var senderId = int.Parse(Context.UserIdentifier);

            if (_userConnections.TryGetValue(receiverId, out var connectionId))
            {
                await Clients.Client(connectionId).SendAsync("UserTyping", senderId, isTyping);
            }
        }

        public async Task JoinGroup(int groupId)
        {
            var userId = int.Parse(Context.UserIdentifier);

            // Check if user is member of the group
            var isMember = await _context.GroupMembers
                .AnyAsync(gm => gm.GroupId == groupId && gm.UserId == userId);

            if (isMember)
            {
                await Groups.AddToGroupAsync(Context.ConnectionId, groupId.ToString());
            }
        }

        public async Task LeaveGroup(int groupId)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupId.ToString());
        }
    }
    //public class ChatHub : Hub
    //{
    //    // 向特定用户发送消息
    //    public async Task SendMessageToUser(string senderUserId, string receiverUserId, string messageContent)
    //    {
    //        // 这里可以添加业务逻辑，如消息持久化
    //        // await _messageService.SaveMessageAsync(senderUserId, receiverUserId, messageContent);

    //        // 发送给特定的连接（用户）
    //        // 注意：需要维护用户ID与ConnectionId的映射关系，通常在OnConnectedAsync和OnDisconnectedAsync中处理
    //        await Clients.User(receiverUserId).SendAsync("ReceiveMessage", senderUserId, messageContent);
    //    }

    //    // 创建或加入群组
    //    public async Task JoinGroup(string groupName)
    //    {
    //        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
    //    }

    //    // 向群组发送消息
    //    public async Task SendMessageToGroup(string senderUserId, string groupId, string messageContent)
    //    {
    //        // 同样可以添加消息持久化逻辑
    //        // await _messageService.SaveGroupMessageAsync(senderUserId, groupId, messageContent);

    //        await Clients.Group(groupId).SendAsync("ReceiveGroupMessage", senderUserId, messageContent);
    //    }

    //    // 客户端连接时调用
    //    public override async Task OnConnectedAsync()
    //    {
    //        // 可以将用户ID和ConnectionId的关联存储起来（例如在字典或分布式缓存中）
    //        var userId = GetUserIdFromContext(Context); // 需要实现该方法从Context（如Claim）获取用户ID
    //                                                    // _connectionManager.AddConnection(userId, Context.ConnectionId);
    //        await base.OnConnectedAsync();
    //    }

    //    // 客户端断开连接时调用
    //    public override async Task OnDisconnectedAsync(Exception exception)
    //    {
    //        // 移除用户ID和ConnectionId的关联
    //        var userId = GetUserIdFromContext(Context);
    //        // _connectionManager.RemoveConnection(userId, Context.ConnectionId);
    //        await base.OnDisconnectedAsync(exception);
    //    }
    //}
}
